home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / dos / communic / pcmail / main / comport.asm < prev    next >
Encoding:
Assembly Source File  |  1994-06-05  |  20.5 KB  |  610 lines

  1. title IBM PC Communications I/O Routines 
  2. ;
  3. ; @(#) comport.asm      Version hoptoad-1.3     87/03/24
  4. ;
  5. ; Orginal code -- Curt Klinsing
  6. ;
  7. ; Changes and updates -- Copyright (c) 1987 Tim Pozar
  8. ; Anyone can use this code for anything, but it is copyright by Tim
  9. ; and you must leave his copyright in the code.
  10. ;
  11. ; ver: 0
  12. ; rev: 2
  13. ; March 13th 1987
  14. ; This code is in a very early stage and should not be let out.
  15. ; Several other extensive functions are planned as well as changes
  16. ; to the current code.
  17. ;
  18. ; 2/20/87 
  19. ;   Changed segment declarations and function names (eg. _function)
  20. ; to fit Microsoft C 4.0 and linker requirements.
  21. ;
  22. ; FUNCTIONS CHANGED/ADDED --
  23. ; set_tty(port_number)
  24. ;   Function to find current settings of the port and set up serial 
  25. ; port for 'baud' and 'lcbyte', and enable DTR.  This will set up the
  26. ; port number base addressed passed to it (eg. 3F8h) and all functions
  27. ; will use this port until the function is used again. (NOT READY FOR USE)
  28. ;
  29. ; reset_tty()
  30. ;   Function to put the port back into the state it was when it was 
  31. ; first found by set_tty().  If set_tty() was not called it will not 
  32. ; change the settings of the port. (NOT READY FOR USE)
  33. ;
  34. ; 3/13/87
  35. ; get_msr()
  36. ;   Function to read (get) the byte located in the Modem Status 
  37. ; Register (3FEh).  The table below describes the byte returned.
  38. ;   bit  description
  39. ;    0   Delta Clear to Send (DCTS)
  40. ;        Indicates that the !CTS input to the chip has changed state
  41. ;        since the last time it was read by the processor.
  42. ;    1   Delta Data Set Ready (DDSR)
  43. ;        Indicates that the !DRS input to the chip has changed since 
  44. ;        last time it was read by the processor.
  45. ;    2   Trailing Edge Ring Indicator (TERI)
  46. ;        Indicates that the !RI input to the chip has changed from
  47. ;        an on (logical 1) to an off (logical 0) condition.
  48. ;    3   Delta Rx Line Signal detect (DRLSD)
  49. ;        Indicates that the !RLSD input to the chip has changed state.
  50. ; NOTE: Whenever bit 0, 1, 2, or 3 is set to a logical 1, a modem status
  51. ;       interrupt is generated.
  52. ;
  53. ;    4   Clear to Send (CTS)
  54. ;        This bit is the complement of the clear to send (!CTS) input.
  55. ;        If bit 4 (LOOP) of the MCR is set to a logical 1, this is 
  56. ;        equivalent to RTS in the MCR.
  57. ;    5   Data Set Ready (DSR)
  58. ;        This bit is the complement of the data set ready (!DSR) input.
  59. ;        If bit 4 (LOOP) of the MCR is set to a logical 1, this is 
  60. ;        equivalent to DTR in the MCR.
  61. ;    6   Ring Indicator (RI)
  62. ;        This bit is the complement of the ring indicator (!RI) input.
  63. ;        If bit 4 (LOOP) of the MCR is set to a logical 1, this is 
  64. ;        equivalent to OUT 1 in the MCR.
  65. ;    7   Receive Line Signal Detect (RLSD).
  66. ;        This bit is the complement of the received line signal detect
  67. ;        (!RLSD) input. If bit 4 (LOOP) of the MCR is set to a logical 1,
  68. ;        this is equivalent to OUT 2 in the MCR.
  69. ;
  70. ;   Currently this driver is set up for COM1 (3f8h).
  71. ;   If you are using the interupt driven buffer, take out the code 
  72. ; that enables the DTR so that it doesn't get raised until the vectors
  73. ; are initilized. 
  74. ;
  75. ; 22/04/1987 W.Z. Venema 
  76. ;       set_tty()       baud rate parameter (values as the "baud" macro below)
  77. ;
  78. ; 19/05/1987 W.Z. Venema
  79. ;       outp_char()     made it check for Xon/Xoff from other system
  80.  
  81. _TEXT   SEGMENT BYTE PUBLIC 'CODE'
  82. _TEXT   ENDS
  83. _DATA   SEGMENT BYTE PUBLIC 'DATA'
  84. _DATA   ENDS
  85. CONST   SEGMENT BYTE PUBLIC 'CONST'
  86. CONST   ENDS
  87. _BBS    SEGMENT BYTE PUBLIC 'BBS'
  88. _BBS    ENDS
  89.  
  90. DGROUP  GROUP   CONST, _BBS, _DATA
  91.       ASSUME    CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
  92.  
  93. _TEXT      SEGMENT
  94. ;
  95. ;A set of Lattice C and MSC callable functions to support
  96. ;interrupt driven character I/O on the  IBM PC. Input
  97. ;is buffered, output is polled.
  98. ;
  99. ;added functions (TMP) --
  100. public  _set_tty        ;find current settings, and initialize 
  101.                         ;comm port to 8 bits and set DTR
  102. public  _reset_tty      ;reset to settings that set_tty() found
  103. public  _get_msr        ;get MSR byte from port.
  104. ;
  105. ;original functions --
  106. public  _init_comm      ;initialize the comm port interupts,
  107. public  _uninit_comm    ;remove initialization,
  108. public  _set_xoff       ;enable/disable XON/XOFF,
  109. public  _get_xoff       ;read XON/XOFF state,
  110. public  _rcvd_xoff      ;returns true if XOFF rcvd,
  111. public  _sent_xoff      ;true if XOFF sent,
  112. public  _inp_cnt        ;returns count of rcv chars,
  113. public  _inp_char       ;get one char from buffer,
  114. public  _inp_flush      ;flush input buffer,
  115. public  _outp_char      ;output a character,
  116. ;
  117. ;A better description can be found in the comment
  118. ;block  in each function.
  119. ;
  120. ;       assume  cs:pgroup
  121. ;
  122. FALSE   EQU     0
  123. TRUE    EQU     NOT FALSE
  124. ;
  125. BASE    EQU     03F8H   ;BASE FOR SERIAL BOARD
  126. ;
  127. LCR     equ     BASE+3  ; Line control register
  128. IER     equ     BASE+1  ; Interrup Enable Register
  129. MCR     EQU     BASE+4  ;modem control register
  130. MDMSTA  EQU     BASE+5  ;line status register
  131. MDMMSR  EQU     BASE+6  ;modem status register
  132. MDMBAD  EQU     BASE    ;lsb baud resgister
  133. EnblDRdy equ    01H     ; enable 'data-ready' interrupt bit
  134. IntCtlr  EQU    21H     ;OCW 1 FOR 8259 CONTROLLER
  135. EnblIRQ4 EQU    0EFH    ;Enable COMMUNICATIONS (IRQ4)
  136. dataport EQU    BASE    ;transmit/receive data port
  137. MaskIRQ4 EQU    10H     ;BIT TO DISABLE COMM INTERRUPT (IRQ4)
  138.  
  139. MDMCD   EQU     80H     ;mask for carrier dectect
  140. SETBAU  EQU     80H     ;code for Divisor Latch Access Bit
  141. MDMTBE  EQU     20H     ;8250 tbe flag
  142. MDMBRK  EQU     40H     ;command code for 8250 break
  143. LINMOD  EQU     03H     ;line mode=8 bit, no parity
  144. MDMMOD  EQU     0BH     ;modem mode = DTR and RTS HIGH
  145. STOP2   EQU     04H     ;BIT FOR TWO STOP BITS IF BAUD<300
  146. RS8259  EQU     20H     ;OCW 3 FOR 8259
  147. RSTINT  EQU     64H     ;SPECIFIC EOI FOR COMM INTERRUPT 
  148. XOFF    EQU     13H     ;XOFF character
  149. XON     EQU     11H     ;XON character
  150. ;
  151. ;       MISCELLANEOUS EQUATES
  152. ;
  153. CR      EQU     13
  154. LF      EQU     10
  155. DosCall EQU     33      ;INTERRUPT NUMBER FOR DOS CALL  
  156. CNSTAT  EQU     11      ;FUNCTION NUMBER FOR CONSOLE STATUS
  157. CNIN    EQU     1       ;FUNCTION NUMBER FOR CONSOLE INPUT
  158. BUFSIZ  EQU     512     ;Max NUMBER OF CHARS
  159. SetIntVect  EQU 25H     ;SET INTERRUPT VECTOR FUNCTION NUMBER
  160.  
  161. ;
  162. ; Communication parameters --
  163. ;
  164. baud    equ     12      ; 1047 =  110 (are you kidding?)
  165.                         ;  384 =  300
  166.                         ;   96 = 1200
  167.                         ;   48 = 2400
  168.                         ;   24 = 4800
  169.                         ;   12 = 9600
  170. parity  equ     00000b  ;00000 = none
  171.                         ;01000 = odd
  172.                         ;11000 = even
  173. stopbit equ     000b    ;  000 = 1 bit
  174.                         ;  100 = 2 bits
  175. wordlth equ     11b     ;   10 = 7 bits
  176.                         ;   11 = 8 bits
  177. lcbyte  equ     parity+stopbit+wordlth      ;line control byte
  178. div_on  equ     80h     ;divisor latch access bit (DLAB)
  179.  
  180. ;
  181. ;       DUMP BUFFER, COUNT AND POINTER.  
  182. ;
  183. CIRC_BUF DB     BUFSIZ DUP(?)   ;ALLOW 512 MaxIMUM BUFFERED CHARACTERS
  184. BUF_TOP EQU     $ - 1           ;KEEP TRACK OF THE TOP OF THE BUFFER
  185. CIRC_TOP DW     BUF_TOP         ;
  186. ;
  187. CIRC_IN DW      OFFSET CIRC_BUF ;POINTER TO LAST CHAR. PLACED IN BUFFER
  188. CIRC_CUR DW     OFFSET CIRC_BUF ;POINTER TO NEXT CHAR. TO BE RETRIEVED FROM
  189.                                 ; BUFFER
  190. CIRC_CT DW      0               ;COUNT OF CHARACTERS USED IN BUFFER
  191. SNT_XOFF DB     FALSE           ;FLAG TO CHECK IF AN XOFF HAS BEEN SEND
  192. GOT_XOFF  DB    FALSE           ;FLAG TO CHECK IF AN XOFF HAS BEEN RECEIVED
  193. SEE_XOFF  DB    FALSE           ;FLAT TO SEE IF WE ARE INTERESTED IN XON/XOFF
  194. ;
  195. ;
  196. ; set_tty()
  197. ;
  198. _set_tty proc near
  199.         push    bp
  200.         mov     bp,sp           ; wzv C calling standard
  201. ;        mov     dx,mcr
  202. ;        in      al,dx           ; get modem parameters
  203. ;        mov     MCR_BYTE,al     ; save them
  204.         mov     dx,lcr
  205. ;        in      al,dx           ; get line parameters
  206. ;        mov     LCR_BYTE,al     ; save them
  207.         mov     al,div_on
  208.         out     dx,al           ; set 8250 for baud rate selection
  209.         ; can the baud rate divisor be read to save the settings?
  210.         ; if so, stick the code here.
  211.         mov     ax,[bp+4]       ; was mov ax,baud /wzv
  212.         mov     dx,mdmbad
  213.         out     dx,al           ; low byte divisor
  214.         mov     al,ah
  215.         inc     dx
  216.         out     dx,al           ; high byte divisor
  217.         mov     dx,lcr
  218.         mov     al,lcbyte
  219.         out     dx,al           ; set line control reg.
  220.         mov     dx,mcr
  221.         in      al,dx
  222.         or      al,mdmmod
  223.         out     dx,al           ; set DTR high
  224. flsh:   mov     dx,dataport
  225.         in      al,dx
  226.         mov     dx,mdmsta
  227.         in      al,dx
  228.         and     al,1
  229.         jnz     flsh
  230.       
  231.         pop     bp
  232.         ret
  233.  
  234. _set_tty endp
  235.  
  236.  
  237. _reset_tty proc near
  238.         push    bp
  239.  
  240.         pop     bp
  241.         ret
  242.  
  243. _reset_tty endp
  244.  
  245. _get_msr proc near
  246.         push    bp
  247.         push    ds              ; save data segment
  248.         push    cs
  249.         pop     ds
  250.  
  251.         xor     ax,ax
  252.         mov     dx,MDMMSR
  253.         in      al,dx
  254.  
  255.         pop     ds
  256.         pop     bp
  257.         ret
  258.  
  259. _get_msr endp
  260.  
  261. ;
  262. ; set_xoff(flag)         Enable (flag != 0) or disable
  263. ;int flag;              (flag == 0) XON/ XOFF protocol
  264. ;                       for the character input stream.
  265. ;If enabled, an XOFF will be sent when  the buffer
  266. ;reaches 3/4 full. NOTE: an XON will not be sent auto-
  267. ;matically. Your program must do it when it sees
  268. ;the _rcvd_xoff() flag,  and ready for more chars.
  269. ;
  270. _set_xoff proc near
  271.         push    bp
  272.         mov     bp,sp           ; wzv C calling standard
  273.         PUSH    DS              ;SAVE DATA SEGMENT
  274.         mov     bx,[bp+4]       ; wzv C calling standard
  275.         push    cs
  276.         pop     ds              ; move code seg addr to data seg reg.
  277.         cmp     bx,0
  278.         jnz     to_on
  279.         mov     see_xoff,FALSE
  280.         jmp     done1
  281. to_on:  mov     see_xoff,TRUE
  282. done1:  pop     ds
  283.         pop     bp
  284.         ret
  285. _set_xoff endp
  286. ;
  287. ;flag = get_xoff()      Returns the current setting
  288. ;                       of the XON/ XOFF flag set
  289. ;by set_xoff(), above.
  290. ;
  291. _get_xoff proc near
  292.         push    bp
  293.         push    ds              ; save data reg
  294.         push    cs
  295.         pop     ds              ; move code seg addr to data seg reg.
  296.         xor     ax,ax
  297.         mov     al,see_xoff
  298.         pop     ds
  299.         pop     bp
  300.         ret
  301. _get_xoff endp
  302. ;
  303. ;flag = sent_xoff();    Returns true if an XOFF
  304. ;                       character was sent, indicating
  305. ;the receive buffer is  3/4 full.
  306. ;
  307. _sent_xoff proc  near
  308.         push    bp
  309.         push    ds              ; save data reg
  310.         push    cs
  311.         pop     ds              ; move code seg addr to data seg reg.
  312.         xor     ax,ax
  313.         mov     al,snt_xoff
  314.         pop     ds
  315.         pop     bp
  316.         ret
  317. _sent_xoff endp
  318. ;
  319. ; rcvd_xoff()            Returns true if an XOFF was
  320. ;                       received; will return false as
  321. ;soon as an XON is received. Does not effect data output,
  322. ;only indicates the above. (Obviously useless for binary
  323. ;data.)
  324. ;
  325. _rcvd_xoff proc  near
  326.         push    bp
  327.         push    ds              ; save data reg
  328.         push    cs
  329.         pop     ds              ; move code seg addr to data seg reg.
  330.         xor     ax,ax
  331.         mov     al,got_xoff
  332.         pop     ds              ; restore data reg
  333.         pop     bp
  334.         ret
  335. _rcvd_xoff endp
  336. ;
  337. ;count = inp_cnt()       Returns the number of characters
  338. ;                       available in the input buffer.
  339. ;
  340.  
  341. _inp_cnt proc near       
  342.         push    bp
  343.         push    ds              ; save data segment
  344.         push    cs
  345.         pop     ds              ; move code seg addr to data seg reg
  346.         mov     ax,circ_ct
  347.         pop     ds
  348.         pop     bp
  349.         ret
  350. _inp_cnt endp
  351. ;
  352. ; inp_flush()    Flush the input buffer.
  353. ;
  354. _inp_flush proc  near    
  355.         push    bp
  356.         push    ds              ; save data reg
  357.         push    cs
  358.         pop     ds              ; move code seg addr to data seg reg.
  359.         mov     bx,offset circ_buf
  360.         mov     circ_in,bx      
  361.         mov     circ_cur,bx
  362.         xor     ax,ax
  363.         mov     circ_ct,ax
  364.         pop     ds
  365.         pop     bp
  366.         ret
  367. _inp_flush endp
  368.  
  369. ; --------- Init -----------------------------------
  370. ; Program initialization:
  371. ;   --  Set up vector for RS232 interrupt (0CH)
  372. ;   --  Enbl IRQ4
  373. ;   --  Enbl RS232 interrupt on data ready
  374. ;
  375. ; ---------------------------------------------------
  376.  
  377. _init_comm proc  near
  378.         push    bp
  379.         cli
  380.  
  381. ;  ---- Set up  INT x'0C' for IRQ4
  382.  
  383.         push    ds
  384.         push    cs
  385.         pop     ds              ;cs to ds
  386.         mov     dx,offset IntHdlr ;relative adddres of interrupt handler
  387.         mov     al,0cH          ;interrupt number for comm.
  388.         mov     ah,SetIntVect   ;function number for setting int vector
  389.         int     DosCall         ;set interrupt in 8086 table
  390.         pop     ds              ;restore DS
  391.  
  392. ;  ---- Enbl IRQ4 on 8259 interrupt controller
  393.  
  394.         cli
  395.  
  396.         in      al,IntCtlr      ; get current masks 
  397.         and     al,EnblIRQ4     ; Reset IRQ4 mask
  398.         out     IntCtlr,al      ; And restore to IMR
  399.  
  400. ;  ---   Enbl 8250 data ready interrupt
  401.  
  402.         mov     dx,LCR          ; DX ==> LCR
  403.         in      al,dx           ; Reset DLAB for IER access
  404.         and     al,7FH
  405.         out     dx,al
  406.         mov     dx,IER          ; Interrupt Enbl Register
  407.         mov     al,EnblDRdy     ; Enable 'data-ready' interrupt
  408.         out     dx,al
  409.  
  410. ;  ---   Enbl OUT2 on 8250
  411.  
  412.         mov     dx,MCR          ; modem control register        
  413.         in      al,dx           ; Enable OUT2
  414.         or      al,08h            ; find out what is in there and
  415.         out     dx,al            ; enable the DTR
  416.  
  417.         sti
  418.  
  419.         pop     bp
  420.         ret
  421. _init_comm endp
  422. ;
  423. ; uninit_comm()          Removes the interrupt structure
  424. ;                       installed by _init_comm(). Must be
  425. ;done before passing control to the DOS, else chars received
  426. ;will be stored into the next program loaded!
  427. ;
  428. _uninit_comm proc near
  429.         push    bp
  430. ; ---   Disable IRQ4 on 8259
  431.  
  432.         cli
  433.         in      al,IntCtlr      ;GET OCW1 FROM 8259
  434.         or      al,MaskIRQ4     ;DISABLE COMMUNICATIONS INTERRUPT
  435.         out     IntCtlr,al
  436.  
  437. ; ---   Disable 8250 data ready interrupt
  438.         
  439.         mov     dx,LCR          ; DX ==> LCR
  440.         in      al,dx           ; Reset DLAB for IER access
  441.         and     al,7FH
  442.         out     dx,al
  443.         mov     dx,IER          ; Interrupt Enbl Register
  444.         mov     al,0            ; Disable all 8250 interrupts
  445.         out     dx,al
  446.  
  447. ;  ---   Disable OUT2 on 8250
  448.  
  449.         mov     dx,MCR          ; modem control register        
  450.         mov     al,0            ; drop DTR
  451.         out     dx,al
  452.  
  453.         sti
  454.         pop     bp
  455.         ret
  456. _uninit_comm endp
  457. ;
  458. ;char  inp_char()      Return a character from the input
  459. ;                      buffer. Assumes you have called
  460. ;inp_cnt() to see if theres any characters to get.
  461. ;
  462. _inp_char proc near      
  463.         push    bp
  464.         push    ds              ; save data reg
  465.         push    cs
  466.         pop     ds              ; move code seg addr to data seg reg.
  467.         mov     bx,circ_cur
  468.         xor     ax,ax
  469.         mov     al,[bx]         ;get next char from circ_buf
  470.         DEC     circ_ct         ;decrement circ_buf COUNT
  471.         CMP     bx,circ_top     ;ARE WE AT THE TOP OF THE circ_buf?
  472.         JZ      reset_cur       ;JUMP IF SO
  473.         INC     bx              ;ELSE, BUMP PTR
  474.         JMP SHORT upd_cur
  475. reset_cur:
  476.         mov     bx,OFFSET circ_buf      ;RESET circ_in TO BOTTOM OF BUF.
  477. upd_cur:
  478.         mov     circ_cur,bx             ;SAVE NEW PTR
  479.         xor     cx,cx
  480.         mov     cl,see_xoff     ;check if interested in xon/xoff
  481.         cmp     cl,TRUE
  482.         jnz     clnup2          ;not interested, so goto return
  483.         cmp     snt_xoff,TRUE   ;have we sent an xoff?
  484.         jnz     clnup2          ;no, so return
  485.         cmp     circ_ct,80h     ;yes, so see in buf is now emptying
  486.         jg      clnup2          ;not empty enuf to send xon, jump to ret
  487.         mov     snt_xoff,FALSE
  488.         mov     cl,XON
  489.         push    ax              ; save char
  490.         call    comout
  491.         pop     ax
  492. clnup2: pop     DS              ;GET BACK ENTERING DS
  493.         pop     bp
  494.         ret
  495. _inp_char endp
  496. ;
  497. ; outp_char(c)           Output the character to the
  498. ;char c;                serial port. This is not buffered
  499. ;                       or interrupt driven.
  500. ;
  501. _outp_char proc  near
  502.         push    bp
  503.         mov     bp,sp
  504.     push    ds        ; save data segment register /wzv
  505.     push    cs        ; copy code segment register /wzv
  506.     pop    ds        ; to data segment register /wzv
  507. w_Xon:  test    got_Xoff,TRUE    ; shut up if Xoff received / wzv
  508.         jnz     w_Xon
  509.         mov     cl,[bp+4]
  510.         sti
  511.         call    comout
  512.     pop    ds        ; restore data segment register / wzv
  513.         pop     bp
  514.         ret
  515. _outp_char endp
  516. ;
  517. ;Local  subroutine: output CL to the port.
  518. ;
  519. comout: mov     dx,MDMSTA       
  520.         in      al,dx           ; get 8250 status
  521.         and     al,MDMTBE       ; check for transmitter ready
  522.         jz      comout          ; jump if not to wait
  523.         mov     al,cl           ; get char to al
  524.         mov     dx,dataport     
  525.         out     dx,al           ; output char to 8251
  526.         ret
  527. ;
  528. ;       RECEIVE INTERRUPT HANDLER (CHANGED TO PLACE CHARACTERS IN A
  529. ;        CIRCULAR circ_buf AND TO SEND AN XOFF IF THE circ_buf IS MORE THAN
  530. ;        3/4 FULL - S.G.)
  531. ;
  532. IntHdlr:
  533.         CLI
  534.         push    cx
  535.         push    dx
  536.         push    bx
  537.         push    ax
  538.         push    ds
  539.         mov     ax,cs           ;get cur code segment
  540.         mov     ds,ax           ;and set it as data segment
  541.         mov     bx,circ_in      ;GET circ_buf IN PTR
  542.         mov     DX,dataport     ;GET DATA PORT NUMBER
  543.         IN      AL,DX           ;GET RECEIVED CHARACTER
  544. ;       push    ax
  545. ;       push    dx   
  546. ;       xor     ax,ax
  547. ;       xor     dx,dx
  548. ;       mov     dl,al
  549. ;       mov     ah,2
  550. ;       int     DosCall
  551. ;       pop     dx
  552. ;       pop     ax
  553.         xor     cx,cx
  554.         mov     cl,see_xoff     ;check if interested in xon/xoff
  555.         cmp     cl,TRUE
  556.         jnz     ck_full         ;not interested goto ck if buf full
  557.         mov     cl,al           ;put char in cl for testing
  558.         and     cl,7fh          ;turn off any parity bits 
  559.         cmp     cl,XOFF         ;see if we got an xoff
  560.         jnz     ck_xon
  561.         mov     got_Xoff,TRUE   ; code for handling xon/xoff from remote
  562.         jmp     clnup
  563. ck_xon: cmp     cl,XON
  564.         jnz     reg_ch
  565.         mov     got_Xoff,FALSE
  566.         jmp     clnup
  567. ;
  568. ;Normal character; not  XON/XOFF, or XON/XOFF disabled.
  569. ;
  570. reg_ch: test    snt_Xoff,TRUE   ;SEE IF sentXoff IS SET
  571.         jnz     ck_full         ;IF SO, DON'T SEND ANOTHER XOFF
  572.         CMP     circ_ct,(BUFSIZ * 3)/4  ;ALLOW BUF TO BECOME 3/4 FULL BEFORE
  573.                                         ; SENDING XOFF
  574.         jb      savch           ;IF IT'S OK, CONTINUE
  575.         push    ax              ;SAVE CHARACTER
  576.         mov     CL,XOFF         ;GET XOFF CHARACTER
  577.         mov     snt_Xoff,TRUE  ;RESET sentXoff
  578.         call    comout          ; AND SEND IT
  579.         pop     ax              ;RETRIEVE CHARACTER
  580.         JMP SHORT savch         ;IF WE'RE HERE, THE circ_buf HAS BUFSIZ-80H
  581.                                 ;  CHARACTERS
  582. ck_full:
  583.         CMP     circ_ct,BUFSIZ  ;SEE IF circ_buf ALREADY FULL
  584.         JZ      clnup           ; JUMP IF SO, DO NOT PLACE CHARACTER IN BFR
  585. savch:                          
  586.         mov     [bx],AL         ;SAVE NEW CHARACTER IN circ_buf
  587.         inc     circ_ct         ;BUMP circ_buf COUNT
  588.         CMP     bx,circ_top     ;ARE WE AT THE TOP OF THE circ_buf?
  589.         JZ      reset_in        ;JUMP IF SO
  590.         inc     bx              ;ELSE, BUMP PTR
  591.         JMP SHORT into_buf
  592. reset_in:
  593.         mov     bx,OFFSET circ_buf      ;RESET circ_in TO BOTTOM OF BUF.
  594. into_buf:
  595.         mov     circ_in,bx              ;SAVE NEW PTR
  596. clnup:
  597.         mov     AL,RSTINT
  598.         OUT     RS8259,AL       ;ISSUE SPECIFIC EOI FOR 8259
  599.         pop     ds              ;GET BACK ENTERING DS
  600.         pop     ax
  601.         pop     bx
  602.         pop     dx
  603.         pop     cx
  604.         sti
  605.         iret
  606.  
  607. _TEXT   ENDS
  608.  
  609. end
  610.